/*
Acess OS
Virtual File System Version 1
HEADER
*/
/**
 \file vfs.h
 \brief Virtual Filesystem Interface
*/
#ifndef _VFS_H
#define _VFS_H

#define MAX_PATH_LENGTH	255	//!< Maximum Path Length

/**
 \struct s_vfs_node
 \brief Node information structure
 
 The type #vfs_node is the core of the Acess VFS.
*/
struct s_vfs_node {
	char	*name;	//!< Filename
	 int	nameLength;	//!< Length of name
	
	Uint	inode;	//!< ID Number used by driver
	Uint64	length;	//!< Length
	Uint	impl;	//!< Extra Variable for driver (Used by DevFS as driver ID)
	void	*ImplPtr;	//!< Extra Variable for driver
	
	Uint32	uid;	//!< User ID
	Uint32	gid;	//!< Group ID
	Uint16	mode;	//!< Mode (Permissions)
	Uint16	flags;	//!< Flags
	Uint64	atime;	//!< Last Accessed Time
	Uint64	mtime;	//!< Last Modified Time
	Uint64	ctime;	//!< Creation Time
	
	//! Read from Node
	 int	(*read)(struct s_vfs_node *node, Uint64 offset, Uint64 length, void *buffer);
	//! Write to Node
	 int	(*write)(struct s_vfs_node *node, Uint64 offset, Uint64 length, void *buffer);
	//! Close Node
	 int	(*close)(struct s_vfs_node *node);
	//! Read from Directory
	struct s_vfs_node*	(*readdir)(struct s_vfs_node *node, int dirPos);
	//! Find an item in a Directory
	struct s_vfs_node*	(*finddir)(struct s_vfs_node *node, char *filename);
	//! Make a node in a Directory
	struct s_vfs_node*	(*mknod)(struct s_vfs_node *node, char *filename, int flags);
	//! Remove the node
	 int	(*relink)(struct s_vfs_node *node, char *NewName);
};
typedef struct s_vfs_node	vfs_node;	//!< VFS Node Type


#define ROOTFS_ID	0x1AC	//!< RootFS Fileystem ID
#define DEVFS_ID	0x1AD	//!< DevFS Filesystem ID
#define INITROMFS_ID	0x1AE	//!< InitRomFS Fileystem ID
#define PROCFS_ID	0x1AF	//!< ProcFS Fileystem ID

/**
 * \struct sVFS_Driver
 * \brief VFS Driver Information Structure
 */
struct sVFS_Driver {
	struct sVFS_Driver	*Next;
	char	*Name;
	vfs_node*	(*InitDevice)(char *Device, char **Options);
	 int	(*IOCtl)(vfs_node *Node, int Id, void *Data);
	Uint16	*MBRIds;
	Uint64	*GPTIds;
};
typedef struct sVFS_Driver	tVFS_Driver;


/* VFS.C */
/**
 \var vfs_node	NULLNode
 \brief Node equivilent to ""
 
 This is a VFS Node that is used as a placeholder
 for an empty directory entry by vfs_node.readdir
*/
extern vfs_node	NULLNode;

/**
 \fn int vfs_addfs(Uint16 ident, vfs_node* (*initDev)(char* device, char **Options))
 \brief Adds a filesystem to the VFS Layer
 \param ident	Filesystem identifier
 \param initDev	Function pointer to mount initialiser for filesystem
*/
extern int vfs_addfs(Uint16 ident, vfs_node* (*initDev)(char* device, char **Options)) __attribute__ ((deprecated));

/**
 \fn int VFS_AddDriver(tVFS_Driver *Info)
 \brief Adds a filesystem to the VFS Layer
 \param Info	Driver Information Structure
*/
extern int VFS_AddDriver(tVFS_Driver *Info);

/**
 \fn extern int vfs_removefs(Uint16 ident)
 \brief Removes a filsystem from the VFS layer
 \param ident	Identifier of FS to remove
*/
extern int vfs_removefs(Uint16 ident);

/**
 * \fn vfs_node *VFS_GetNodeAndClose(int fp)
 * \brief Get the vfs_node of the file and closes the pointer
 * \param fp	File ID to get node
 * \return VFS Node Assciated with fp
 */
extern vfs_node *VFS_GetNodeAndClose(int fp);

/**
 * \fn int VFS_ReadAt(int fh, Uint64 Offset, Uint64 Length, void *Buffer)
 * \brief Read bytes from an offset in a file
 * \param fh	File Handle
 * \param Offset	Byte offset in file
 * \param Length	Number of bytes to read
 * \param Buffer	Destination for the data
 * \return Number of bytes read or -1 on error
 */
extern int	VFS_ReadAt(int fh, Uint64 Offset, int Length, void *Buffer);
/**
 * \fn int VFS_WriteAt(int fh, Uint64 Offset, Uint64 Length, void *Buffer)
 * \brief Write bytes from an offset in a file
 * \param fh	File Handle
 * \param Offset	Byte offset in file
 * \param Length	Number of bytes to write
 * \param Buffer	Source for the data
 * \return Number of bytes written or -1 on error
 */
extern int	VFS_WriteAt(int fh, Uint64 Offset, int Length, void *Buffer);

/* INODE.C */
/**
 \fn int inode_initCache()
 \brief Creates a handle for a filesystem
 \return Inode Cache handle
*/
extern int	inode_initCache();

/**
 \fn void inode_clearCache(int handle)
 \brief Clear the cache of all a driver's entries
 \param handle	Driver/Instance handle
*/
extern void	inode_clearCache(int handle);

/**
 \fn int inode_isCached(int handle, Uint64 inode)
 \brief Checks if a node is cached
 \param handle	Cache Handle
 \param inode		Inode ID to check
*/
extern int	inode_isCached(int handle, Uint64 inode);

/**
 \fn vfs_node *inode_getCache(int handle, Uint64 inode)
 \brief Gets a node from the cache
 \param handle	Cache Handle
 \param inode		Inode ID
*/
extern vfs_node	*inode_getCache(int handle, Uint64 inode);

/**
 \fn vfs_node *inode_cacheNode(int handle, Uint64 inode, vfs_node *node)
 \brief Gets a node from the cache
 \param handle	Cache Handle
 \param inode		Inode ID
 \param node		Node pointer to copy from
*/
extern vfs_node	*inode_cacheNode(int handle, Uint64 inode, vfs_node *node);

/**
 \fn void inode_uncacheNode(int handle, Uint64 inode)
 \brief Removes a node from the cache
 \param handle	Cache Handle
 \param inode		Inode ID
*/
extern void	inode_uncacheNode(int handle, Uint64 inode);

#endif
